var LGM = {};

(function(){
  var gameworld = [];
  var _gameOverCallback = null;
  var score = 0;
  var _gameOver = false;

  LGM.getScore = function(){
    return score;
  }

  LGM.setGameworld = function(gw){
    gameworld = gw;
  }

  LGM.getGameworld = function(){
    return gameworld;
  }

  LGM.getGameworldLine = function(){
    return gameworld.reduce(function(sum,value){
      return sum.concat(value);
    },[]);
  }

  LGM.resetGame = function(){

  }

  for(var ix = 0;ix < 4;ix++){
    gameworld.push([0,0,0,0]);
  }
  
  //0 1 2 3
  //4 5 6 7
  //8 9 10 11
  //12 13 14 15
  //helpers.  num = 0-15
  function num2loc(num){
    return [Math.floor(num/4), num%4];
  }

  function loc2num(loc){
    return loc[0]*4 + loc[1];
  }

  function getCloneWorld(wd1){
    var wd2 = [];
    for(var ix = 0;ix < 4; ix++){
      wd2.push([]);
      for(var iy = 0;iy < 4;iy++){
        wd2[ix].push(wd1[ix][iy]);
      }
    }
    return wd2;
  }

  function isEqual(wd1,wd2){
    for(var ix = 0;ix < 4;ix ++){
      for(var iy = 0;iy < 4;iy ++){
        if(wd1[ix][iy] !== wd2[ix][iy]){
          return false;
        }
      }
    }
    return true;
  }

  LGM.findEmptyLoc = function(){
    var ans = [];
    for(var ix = 0;ix < 16;ix++){
      var loc = num2loc(ix);
      if(gameworld[loc[0]][loc[1]] === 0){
        ans.push(loc);
      }
    }

    return ans;
  }

  //添加2
  LGM.addTwo = function(loc){
    gameworld[loc[0]][loc[1]] = 2;
  }
  //添加4
  LGM.addFour = function(loc){
    gameworld[loc[0]][loc[1]] = 4;
  }

  LGM.fillNext = function(){
    var emptySet = LGM.findEmptyLoc();
    if(emptySet.length > 0){
      var index = Math.floor((Math.random())*emptySet.length);
      var loc = emptySet[index];
      if(Math.random() < 0.75){
        LGM.addTwo(loc);
      }else{
        LGM.addFour(loc);
      }
      return true;
    }else{
      return false;
    }
  }

  LGM.moveLeft = function(){
    var ans = [];
    for(var ix = 0;ix < gameworld.length;ix ++){
      var line = [];
      for(var iy = 0;iy < gameworld[ix].length;iy++){
        var num1 = gameworld[ix][iy];
        if(num1 === 0){
          continue;
        }

        var num2 = gameworld[ix][iy+1];
        while(num2 === 0){
          if(iy >= 4){
            num2 = -1;
            break;
          }
          iy++;
          num2 = gameworld[ix][iy+1];
        }

        if(num1 === num2){
          line.push(num1*2);
          score += num1;
          iy++;
        }else{
          line.push(num1);
        }    
      }
      while(line.length<4){
        line.push(0);
      }
      ans.push(line);
    }

    gameworld = ans;
    return ans;
  }

  LGM.moveRight = function(){
    for(var ix=0;ix < gameworld.length;ix++){
      gameworld[ix].reverse();
    }
    LGM.moveLeft();
    for(var ix=0;ix < gameworld.length;ix++){
      gameworld[ix].reverse();
    }
    return gameworld;
  }

  LGM.moveUp = function(){
    LGM.rotateLeft();
    LGM.moveLeft();
    LGM.rotateRight();
    return gameworld;
  }

  LGM.moveDown = function(){
    LGM.rotateRight();
    LGM.moveLeft();
    LGM.rotateLeft();
    return gameworld;
  }

  LGM.rotateLeft = function(){
    var ans = [];
    for(var ix = 0;ix < 4;ix++){
      ans.push([]);
      for(var iy = 0;iy < 4;iy++){
        ans[ix].push(gameworld[iy][3-ix]);
      }
    }
    gameworld = ans;
    return ans;
  }

  LGM.rotateRight = function(){
    var ans = [];
    for(var ix = 0;ix < 4;ix++){
      ans.push([]);
      for(var iy = 0;iy < 4;iy++){
        ans[ix].push(gameworld[3-iy][ix]);
      }
    }
    gameworld = ans;
    return ans;
  }

  //需要预先判断有0否
  LGM.isGameOver = function(){
    for(var ix = 0;ix < 4;ix++){
      for(var iy = 0;iy < 4;iy++){
        if(gameworld[ix][iy+1] && gameworld[ix][iy] === gameworld[ix][iy+1]){
          return false;
        }
        if(gameworld[ix+1] && gameworld[ix][iy] === gameworld[ix+1][iy]){
          return false;
        }
      }
    }
    _gameOver = true;
    return _gameOver;
  }

  LGM.go = function(direction){
    if(_gameOver){
      return;
    }

    var cloneWorld = getCloneWorld(LGM.getGameworld());

    switch(direction){
      case 'ArrowLeft': {
        LGM.moveLeft();
        break;
      }
      case 'ArrowRight':{
        LGM.moveRight();
        break;
      }
      case 'ArrowUp':{
        LGM.moveUp();
        break;
      }
      case 'ArrowDown':{
        LGM.moveDown();
        break;
      }
    }

    //TODO 比对前后是否有变化 若没有 则不动。
    if(isEqual(cloneWorld,LGM.getGameworld())){
      return;
    }

    if(LGM.fillNext()){
      var emptySet = LGM.findEmptyLoc();
      if(emptySet.length === 0){
        if(LGM.isGameOver()){
          console.log('=======GAME OVER=========');
          if(LGM._gameOverCallback){
            LGM._gameOverCallback(score);
          }
        }
      }
      //CHECK IF IS GAME OVER HERE.
    }else{
      //NO ROOM NOW
    }
    // console.log("score is "+ score);
  }

  //2的个数  count@param?
  LGM.genRandomWorld = function(num){
    if(num > 10){
      return false;
    }
    var tmp = [
      [0,0,0,0],
      [0,0,0,0],
      [0,0,0,0],
      [0,0,0,0]];

    LGM.setGameworld(tmp);

    for(var ix = 0;ix < num;ix++){
      LGM.fillNext();
    }

    return gameworld;
  }

  LGM.setGameOverCallback = function(callback){
    _gameOverCallback = callback;
  }

})();